package cn.xeblog.plugin.game.sudoku;

import cn.hutool.core.thread.ThreadUtil;
import cn.xeblog.commons.enums.Game;
import cn.xeblog.plugin.annotation.DoGame;
import cn.xeblog.plugin.game.AbstractGame;
import cn.xeblog.plugin.game.sudoku.enums.Level;
import cn.xeblog.plugin.game.sudoku.enums.PanelSize;
import cn.xeblog.plugin.game.sudoku.enums.RealTimeTip;
import cn.xeblog.plugin.game.sudoku.enums.Theme;
import com.google.common.collect.Lists;
import com.intellij.openapi.ui.ComboBox;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.util.Objects;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;

/**
 * 数独主方法
 *
 * @author ☆程序员鼓励师☆
 * @date 2022/8/12 11:34
 */
@DoGame(Game.SUDOKU)
public class Sudoku extends AbstractGame {

  /**
   * 困难等级
   */
  private Level level;
  /**
   * 面板尺寸
   */
  private PanelSize panelSize;
  /**
   * 实时提示
   */
  private RealTimeTip realTimeTip;
  /**
   * 主题
   */
  private Theme theme;
  /**
   * 提示按钮
   */
  private JButton tips;
  /**
   * 提交按钮
   */
  private JButton commit;
  /**
   * 再来一局按钮
   */
  private JButton another;

  @Override
  protected void init() {
    // 初始化主面板
    super.initMainPanel();

    // 初始化属性
    level = Level.EASY;
    panelSize = PanelSize.MIN;
    realTimeTip = RealTimeTip.DIS_ENABLE;
    theme = Theme.DARK;

    // 设置主面板尺寸
    mainPanel.setMinimumSize(new Dimension(150, 300));
    JPanel menuJPanel = new JPanel();
    menuJPanel.setBounds(10, 10, 100, 340);
    // 添加菜单面板
    mainPanel.add(menuJPanel);

    // 菜单面板添加标题
    JLabel title = new JLabel("摸鱼数独");
    title.setFont(new Font("", Font.BOLD, 14));
    menuJPanel.add(title);

    Box vBox = Box.createVerticalBox();
    // 菜单面板添加垂直盒子
    menuJPanel.add(vBox);

    Dimension selectDimension = new Dimension(30, 30);

    vBox.add(Box.createVerticalStrut(10));

    // 添加"难度选择"文本
    JLabel levelLabel = new JLabel("难度选择：");
    levelLabel.setFont(new Font("", Font.BOLD, 13));
    vBox.add(levelLabel);
    vBox.add(Box.createVerticalStrut(5));

    ComboBox<String> gameLevelBox = level.getComboBox(selectDimension);
    gameLevelBox.addActionListener(
        l -> level = Level.getLevel(Objects.requireNonNull(gameLevelBox.getSelectedItem()).toString()));
    // 添加困难等级下拉框
    vBox.add(gameLevelBox);

    vBox.add(Box.createVerticalStrut(5));

    // 添加"主面板大小"文本
    JLabel sizeLabel = new JLabel("主面板大小：");
    sizeLabel.setFont(new Font("", Font.BOLD, 13));
    vBox.add(sizeLabel);
    vBox.add(Box.createVerticalStrut(5));
    // 面板大小下拉框
    ComboBox<String> gameSizeBox = panelSize.getComboBox(selectDimension);
    gameSizeBox.addActionListener(
        l -> panelSize = PanelSize.getPanelSize(Objects.requireNonNull(gameSizeBox.getSelectedItem()).toString()));
    // 添加面板大小下拉框
    vBox.add(gameSizeBox);

    vBox.add(Box.createVerticalStrut(5));

    // 添加"实时提示"文本
    JLabel tipLabel = new JLabel("实时提示：");
    tipLabel.setFont(new Font("", Font.BOLD, 13));
    vBox.add(tipLabel);
    vBox.add(Box.createVerticalStrut(5));
    // 实时提示下拉框
    ComboBox<String> tipSelectBox = realTimeTip.getComboBox(selectDimension);
    tipSelectBox.addActionListener(
        l -> realTimeTip = RealTimeTip.getRealTimeTip(Objects.requireNonNull(tipSelectBox.getSelectedItem()).toString()));
    // 添加实时提示下拉框
    vBox.add(tipSelectBox);

    vBox.add(Box.createVerticalStrut(5));

    // 添加"主题"文本
    JLabel themeLabel = new JLabel("主题：");
    themeLabel.setFont(new Font("", Font.BOLD, 13));
    vBox.add(themeLabel);
    vBox.add(Box.createVerticalStrut(5));
    // 主题下拉框
    ComboBox<String> themeSelectBox = theme.getComboBox(selectDimension);
    themeSelectBox.addActionListener(
        l -> theme = Theme.getTheme(Objects.requireNonNull(themeSelectBox.getSelectedItem()).toString()));
    // 添加主题下拉框
    vBox.add(themeSelectBox);

    vBox.add(Box.createVerticalStrut(10));

    // 开始按钮
    vBox.add(getStartJButton("开始解题"));
    // 退出游戏按钮
    vBox.add(getExitButton());

    mainPanel.updateUI();
  }

  @Override
  protected void start() {
    // 初始化主面板
    super.initMainPanel();

    // 设置主面板大小
    mainPanel.setMinimumSize(new Dimension(panelSize.getMainWith(), panelSize.getMainHeight()));
    mainPanel.setLayout(new BorderLayout());
    mainPanel.add(Box.createVerticalStrut(10), BorderLayout.NORTH);
    mainPanel.add(Box.createHorizontalStrut(10), BorderLayout.EAST);

    // 数独界面
    SudokuGui sudokuGui = new SudokuGui(level, panelSize, realTimeTip, theme);
    // 主面板添加数独界面
    mainPanel.add(sudokuGui, BorderLayout.CENTER);
    // 添加底部按钮
    JPanel bottomPanel = getBottomPanel(sudokuGui);
    mainPanel.add(bottomPanel, BorderLayout.SOUTH);
    mainPanel.updateUI();

    // 解密  困难以上模式解密可能会比较耗时，异步解密后开启按钮操作
    ThreadUtil.execAsync(() -> sudokuGui.doSolution(Lists.newArrayList(commit, tips, another)));
  }

  /**
   * 创建按钮面板
   */
  private JPanel getBottomPanel(SudokuGui sudokuGui) {
    // 提交按钮
    commit = sudokuGui.getCommitJButton();
    // 提示按钮
    tips = sudokuGui.getTipsJButton();
    // 开始按钮
    another = getStartJButton("再来一局");

    // 设置按钮统一属性
    Dimension buttonDimension = new Dimension(71, 29);
    Lists.newArrayList(commit, tips, another).forEach(b -> {
      // 禁用按钮，困难以上模式解密可能会比较耗时，解密后开启按钮操作
      b.setEnabled(false);
      b.setPreferredSize(buttonDimension);
    });

    JPanel buttonPanel1 = new JPanel();
    // 按钮面板，添加提交按钮
    buttonPanel1.add(commit);
    // 按钮面板，添加提示按钮
    buttonPanel1.add(tips);

    JPanel buttonPanel2 = new JPanel();
    buttonPanel2.add(another);
    // 按钮面板，添加主菜单按钮
    buttonPanel2.add(getMenuJButton(buttonDimension));

    JPanel buttonPanel = new JPanel();
    if (PanelSize.MIN == panelSize) {
      // 小尺寸用边界布局
      buttonPanel.setLayout(new BorderLayout());
      buttonPanel.add(buttonPanel1, BorderLayout.NORTH);
      buttonPanel.add(buttonPanel2, BorderLayout.CENTER);
    } else { // 大尺寸用流式布局
      buttonPanel.setLayout(new FlowLayout());
      buttonPanel.add(buttonPanel1);
      buttonPanel.add(buttonPanel2);
    }

    return buttonPanel;
  }

  /**
   * 主菜单按钮
   *
   * @param buttonDimension 按钮尺寸
   * @return 主菜单按钮
   */
  public JButton getMenuJButton(Dimension buttonDimension) {
    JButton menu = new JButton("主菜单");
    menu.setPreferredSize(buttonDimension);
    // 监听事件-> 返回开始页
    menu.addActionListener(e -> this.init());
    return menu;
  }

  /**
   * 开始按钮
   *
   * @param title 开始按钮标题
   * @return 开始按钮
   */
  public JButton getStartJButton(String title) {
    JButton start = new JButton(title);
    // 监听事件-> 开始游戏
    start.addActionListener(e -> start());
    return start;
  }

}